package net.zoneland.knowledge.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import org.json.JSONException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

import com.branchitech.account.ldap.Department;
import com.branchitech.gum.biz.UserCommonService;
import com.branchitech.gum.domain.Organization;
import com.branchitech.gum.domain.UserIdentity;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;

import net.zoneland.knowledge.enums.CmpDnEnum;
import net.zoneland.knowledge.enums.QaBankCmpDnEnum;
import net.zoneland.knowledge.exceptions.UserServiceException;
import net.zoneland.knowledge.model.LoginUserPojo;

/**
 * Mc实现.
 *
 * @author: bcc
 *     2022/3/11
 */
@ConditionalOnProperty(name = "biz.user-service", havingValue = "mc")
@Service
public class UserServiceServiceMc extends AbstractUserService  {

    @Autowired
    private UserCommonService userCommonService;

    /**
     * 本部（总部是否挂载在根目录下）.
     * 如浙江移动公司的人员，公司就是根
     * 选人是要在浙江移动公司，下构造一个省公司
     */
    @Value("${gum.includeBase:false}")
    private boolean includeBase;
    @Value("${gum.baseName:省公司}")
    private String baseName;
    
    @Autowired
    private com.branchitech.gum.biz.UserService mcUserService;

    @Value("${gum.CompanyCode}")
    private String companyCode;

    /**
     * guava缓存，获取内存.
     */
    private static final Cache<String, List<Organization>> cache = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.HOURS).build();

    private static final String CATCH_NAME = "CATCH_NAME";

    @Override
    public LoginUserPojo getUserByUid(final String uid)  throws UserServiceException {
        final LoginUserPojo user = new LoginUserPojo();
        try {
            final Optional<UserIdentity> primaryUser = mcUserService.queryUserIdentityListByLoginName(uid)
                .stream()
                .filter(item -> "0".equals(item.getPrimaryStatus()))
                .findFirst();
            primaryUser.ifPresent(u -> {
                user.setUserID(uid);
                user.setUserName(u.getUserName());
                //用户是二级部门的情况不会取到一级部门，如：浙江移动公司/信息技术部/管理信息部 获取到的是管理信息部
                user.setDepartmentDN(u.getOrgCode());
                user.setDeptName(u.getOrgName());
                final Organization organization = u.getOrganization();
                if (null != organization) {
                    user.setCompanyDN(organization.getOrgCode());
                    user.setCompanyName(organization.getOrgName());
                }
            });
        } catch (Exception e) {
            throw new UserServiceException("getUserByUid error companyCode:" + uid, e);
        }
        return user;
    }

    @Override
    public String getCityId(final LoginUserPojo user) {
        return CmpDnEnum.getCityByValue(user.getCompanyDN());
    }

    @Override
    public List<Organization> queryBranchCompList(boolean includeCommon) throws UserServiceException {
        try {
            return cache.get(CATCH_NAME+includeCommon, () -> {
                List<Organization> rs = new ArrayList<>();
                if (includeCommon) {
                    Organization globalVisible = new Organization();
                    globalVisible.setOrgCode(QaBankCmpDnEnum.COMMON.getValue());
                    globalVisible.setOrgName(QaBankCmpDnEnum.COMMON.getName());
                    rs.add(globalVisible);
                }
                try {
                    if (!includeBase) {
                        final Organization organization = userCommonService.queryOrgInfoByCode(companyCode);
                        organization.setOrgName(baseName);
                        rs.add(organization);
                    }
                    rs.addAll(userCommonService.queryBranchCompList(companyCode));
                    return rs;
                } catch (Exception e) {
                    throw new UserServiceException("queryBranchCompList error companyCode:" + companyCode, e);
                }
            });
        } catch (ExecutionException e) {
            throw new UserServiceException("getUserByUid error includeCommon:"+includeCommon, e);
        }
    }

    @Override
    public List<Organization> queryDeptByCompCode(final String companyCode) throws UserServiceException {
        try {
            return mcUserService.getChildrenOrgListByCode(companyCode);
        } catch (Exception e) {
            throw new UserServiceException("queryDeptByCompCode error companyCode:" + companyCode, e);
        }
    }

    @Override
    public boolean checkUserExists(final String userName, final String orgCode) throws UserServiceException {
        try {
            //全省通用的情况没法验证
            if (QaBankCmpDnEnum.COMMON.getValue().equals(orgCode)) {
                return true;
            }
            final List<UserIdentity> list = userCommonService.queryUserByUserNameAndLoginNameLike(userName, null);
            list.stream().filter(item -> orgCode.equals(item.getOrgCode())).count();
        } catch (JSONException e) {
            throw new UserServiceException("checkUserExists error userName:" + userName, e);
        }
        return true;
    }

    @Override
    public List<String> getUserDeptCodeAndParentDeptCode(final LoginUserPojo loginUserPojo) throws Exception {
        List<String> rs =  Lists.newArrayList(loginUserPojo.getDepartmentDN());
        Organization instance = mcUserService.queryOrgInfoByOrgCode(loginUserPojo.getDepartmentDN());
        while (instance != null) {
            instance =  mcUserService.queryOrgInfoByOrgCode(instance.getParentCode());
            // levelType 0表示部门  1表示公司
            if(null != instance && "0".equals(instance.getLevelType())) {
                rs.add(instance.getOrgCode());
            }
        }
        return rs;
    }

}
